#include "World.h"

void CWorld::loadLevel(String sName)
{
    
    m_Level.load(sName);
    
}

//Update dynamic entities
void CWorld::update(Scalar fTimeStep)
{
    
    doCollisionDetection();
    updateObjects(fTimeStep);
    
}

//Draw the world
void CWorld::draw()
{
    
    m_Level.drawBackground();
    
    for(EntityIterator itEnt = m_pEntities.begin();
        itEnt != m_pEntities.end();
        ++itEnt)
            (*itEnt)->draw();
    
    m_Level.drawForeground();
    
}

CPhysicsPoint* CWorld::addPhysicsPoint(Vector vPos, Scalar fMass, Scalar fRotInertia)
{
    
    m_pPhysicsPoints.push_back( new CPhysicsPoint(vPos, fMass, fRotInertia) );
    return m_pPhysicsPoints.back();
    
}

CEntity* CWorld::addEntity(String sName, Vector vPos, String sTextureName, RGBAColor rgbaColor)
{
    
    CEntity* pNewEnt = new CEntity(sName, vPos, sTextureName, rgbaColor);
    
    m_pEntities.push_back(pNewEnt);
    //if (bColliding)
        m_pCollidingEntities.push_back(pNewEnt);
        
    return pNewEnt;
    
}

CEntity* CWorld::addCollidingEntity(CEntity entity)
{
    //TODO: Look at this function
    //addEntity(entity);
    //m_CollidingEntities.push_back(entity);
    //if (bColliding)
        //m_CollidingEntities.push_back(entity);
        
    //return m_Entities.back();
    
}

CLengthConstraint* CWorld::addLengthConstraint(CPhysicsSegment segment, Scalar fLength)
{
    
    CLengthConstraint* pNewConstraint = new CLengthConstraint(segment, fLength);
    
    m_pConstraints.push_back(pNewConstraint);
    
    return pNewConstraint;
    
}

CSlideConstraint* CWorld::addSlideConstraint(CPhysicsPoint* pSlidingPoint, CSegment segment)
{
    
    CSlideConstraint* pNewConstraint = new CSlideConstraint(pSlidingPoint, segment);
    
    m_pConstraints.push_back(pNewConstraint);
    
    return pNewConstraint;
    
}

CSpringConstraint*  CWorld::addSpringConstraint(CPhysicsSegment segment, Scalar fSpringConstant, Scalar fDampingConstant, Scalar fLength)
{
    
    CSpringConstraint* pNewConstraint = new CSpringConstraint(segment, fSpringConstant, fDampingConstant, fLength);
    
    m_pConstraints.push_back(pNewConstraint);
    
    return pNewConstraint;
    
}

/*
CPlayer* CWorld::addPlayer(CPlayer player)
{
    
    CPlayer* pNewPlayer = new CPlayer(player);
    m_pEntities.push_back(pNewPlayer);
    m_pPlayers.push_back(pNewPlayer);
    
    std::cout << "add " << pNewPlayer << std::endl;
    
    return pNewPlayer;
    
}
*/
void CWorld::doCollisionDetection()
{
    
    //First do (non-player) entity-entity collisions
    //Iterate through pairs of colliding entities
    for(EntityIterator itEnt1 = m_pCollidingEntities.begin(), itEnt2 = ++m_pCollidingEntities.begin();
        itEnt1 != m_pCollidingEntities.end();
        itEnt2 = ++itEnt1, ++itEnt2)
            for(; itEnt2 != m_pCollidingEntities.end(); itEnt2++)
                CEntity::collideEntities(*itEnt1, *itEnt2);
            
    //Now do (non-player) entity-level collisions
    for(EntityIterator itEnt = m_pCollidingEntities.begin();
        itEnt != m_pCollidingEntities.end();
        ++itEnt)
            m_Level.collideWith(*itEnt);
    
    
    /*
    //Now do player-player collisions
    //Iterate through pairs of players
    for(PlayerIterator itPlayer1 = m_pPlayers.begin(), itPlayer2 = ++m_pPlayers.begin();
        itPlayer1 != m_pPlayers.end();
        itPlayer2 = ++itPlayer1, ++itPlayer2)
            for(; itPlayer2 != m_pPlayers.end(); itPlayer2++)
                CPlayer::collidePlayers(*itPlayer1, *itPlayer2);
    */
    /*
    //Now do player-level collisions
    for(PlayerIterator itPlayer = m_pPlayers.begin();
        itPlayer != m_pPlayers.end();
        ++itPlayer) {
            m_Level.collideWith(*itPlayer);
        }
    */
}

void CWorld::updateObjects(Scalar fTimeStep)
{
    
    for(PhysicsPointIterator itPoint = m_pPhysicsPoints.begin();
        itPoint != m_pPhysicsPoints.end();
        ++itPoint) {
            (*itPoint)->update(fTimeStep);
        }
    
    for(EntityIterator itEnt = m_pEntities.begin();
        itEnt != m_pEntities.end();
        ++itEnt) {
            (*itEnt)->update(fTimeStep);
        }
        
    for(ConstraintIterator itConstraint = m_pConstraints.begin();
        itConstraint != m_pConstraints.end();
        ++itConstraint) {
            (*itConstraint)->update();
        }
    
}


/*
int iOverlapCount = CEntity::countCollidingPixels(ent1, ent2);
            
            if (iOverlapCount) {
                
                //The entities have collided
                
                if (ent1.isSolid() && ent2.isSolid()) {
                    
                    //Use finite differences to find the gradient of the collision region
                    int iDX = CEntity::countCollidingPixels(ent1, ent2, 1, 0) - CEntity::countCollidingPixels(ent1, ent2, -1, 0);
                    int iDY = CEntity::countCollidingPixels(ent1, ent2, 0, 1) - CEntity::countCollidingPixels(ent1, ent2, 0, -1);
                    
                    Vector vCollisionNormal = Vector(iDX, iDY);
                    
                    //Perform collision response
                    
                    
                }
                
                //Inform entities of their collision
                //ent1.onCollide(ent2);
                //ent2.onCollide(ent1);              
*/
